﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Threading.Tasks;
using Coding4Fun.Toolkit.Controls;
using RATSharpW7.View;

namespace RATSharpW7.ViewModel
{
    /// <summary>
    /// Generic data Model view for whole collections.
    /// </summary>
    /// <typeparam name="T">Single object which shoud be loaded</typeparam>
    /// <typeparam name="TT">Datacontainer for object.</typeparam>
    [DataContract]
    public class CollectionViewModel<T, TT> : ViewModel where TT : List<T>
    {
        [DataMember]
        public ObservableCollection<T> loadedObjectsDataSource { get; set; }

        public CollectionViewModel()
        {
            this.loadedObjectsDataSource = new ObservableCollection<T>();
        }

        /// <summary>
        /// Our observable datasource collection
        /// </summary>
        public ObservableCollection<T> DataSource
        {
            get
            {
                if (this.loadedObjectsDataSource == null)
                {
                    this.loadedObjectsDataSource = new ObservableCollection<T>();
                }
                return this.loadedObjectsDataSource;
            }
        }

        protected void notifyChangeModel(Task<TT> task)
        {
            task.ContinueWith(t =>
            {
                Exception ex = t.Exception;

                //switch to UI thread
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    if (ex != null && t.Result == null)
                    {
                        ViewUtils.reportError(ex != null ? ex.Message : "unknown");
                    }
                    else
                    {
                        this.loadedObjectsDataSource.Clear();
                        foreach (T fav in t.Result)
                        {
                            this.loadedObjectsDataSource.Add(fav);
                        }
                    }
                });
            });
        }

        /// <summary>
        /// Same method as notifyChangeModel event, but instead of 
        /// handling errors and so on only the event handler is notified.
        /// </summary>
        /// <param name="task">Rest task</param>
        /// <param name="eventHandler">eventHandler</param>
        protected void notifyChangeModel(Task<TT> task, EventHandler<ModifyReservationEventArgs> eventHandler)
        {
            task.ContinueWith(t =>
            {
                TT resList = t.Result;
                Exception ex = t.Exception;
                //switch to UI
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    if (ex != null || resList == null)
                    {
                        eventHandler(this, new ModifyReservationEventArgs(false, ex != null ? ex.Message : "unknown"));
                    }
                    else
                    {
                        DataSource.Clear();
                        foreach (T fav in resList)
                        {
                            DataSource.Add(fav);
                        }
                        eventHandler(this, new ModifyReservationEventArgs(true, ""));
                    }
                });
            });
        }

    }
}
